From a547bf3506b822d5ff4c1f1c6c4a15c63dd2d90e Mon Sep 17 00:00:00 2001
From: Kit La Touche <kit@transneptune.net>
Date: Mon, 11 Nov 2024 22:57:35 -0500
Subject: Style sidebar and message input

---
 ui/routes/(app)/ch/[channel]/+page.svelte | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'ui/routes/(app)/ch/[channel]/+page.svelte')

diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index 0961665..6348e5c 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -22,4 +22,13 @@
     );
     overflow: auto;
   }
+  .create-message {
+    position: fixed;
+    bottom: 0.5rem;
+    width: calc(100% - var(--nav-width) - 2rem);
+    @media (width <= 640px) {
+      width: 100%;
+      left: 0;
+    }
+  }
 </style>
-- 
cgit v1.2.3


From c9b3394e9fc2cf6eb505ab03a6479eae996ed6e9 Mon Sep 17 00:00:00 2001
From: Kit La Touche <kit@transneptune.net>
Date: Wed, 1 Jan 2025 18:09:46 -0500
Subject: Just oh so many styles

---
 ui/app.css                                |  6 +++
 ui/lib/components/Message.svelte          | 40 +--------------
 ui/lib/components/MessageRun.svelte       | 15 +-----
 ui/routes/(app)/+layout.svelte            | 54 ++------------------
 ui/routes/(app)/ch/[channel]/+page.svelte | 20 +-------
 ui/styles/active-channel.css              |  3 ++
 ui/styles/app-bar.css                     |  1 +
 ui/styles/app-layout.css                  | 56 +++++++++++++++++++++
 ui/styles/messages.css                    | 83 +++++++++++++++++++++++++++++++
 ui/styles/sidebar.css                     | 11 ++++
 ui/styles/textarea.css                    | 38 ++++++++++++++
 ui/styles/variables.css                   | 28 ++++++++---
 12 files changed, 228 insertions(+), 127 deletions(-)
 create mode 100644 ui/styles/active-channel.css
 create mode 100644 ui/styles/app-layout.css
 create mode 100644 ui/styles/messages.css
 create mode 100644 ui/styles/textarea.css

(limited to 'ui/routes/(app)/ch/[channel]/+page.svelte')

diff --git a/ui/app.css b/ui/app.css
index c4b464b..a945c6a 100644
--- a/ui/app.css
+++ b/ui/app.css
@@ -2,11 +2,17 @@
 @import url("styles/variables.css");
 @import url("styles/overscroll.css");
 @import url("styles/app-bar.css");
+@import url("styles/app-layout.css");
 @import url("styles/sidebar.css");
+@import url("styles/active-channel.css");
+@import url("styles/messages.css");
+@import url("styles/textarea.css");
 
 /* Debugging */
+/* * /
 div {
   outline: 1px dashed grey;
   background-color: var(--colour-background);
   box-shadow: 5px 5px 5px var(--colour-border);
 }
+/* */
diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte
index cfadbba..6918b5d 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -26,8 +26,8 @@
 </script>
 
 <div
-    class="message relative"
-    class:bg-warning-800={deleteArmed}
+    class="message"
+    class:delete-armed={deleteArmed}
     role="article"
     data-at={at}
     {onmouseleave}
@@ -43,39 +43,3 @@
     {@html renderedBody}
   </section>
 </div>
-
-<style>
-  .message .handle {
-    display: none;
-  }
-  .message:hover .handle {
-    display: flex;
-  }
-  .message-body {
-    overflow: auto;
-    max-width: 80vw;
-    @media (width > 640px) {
-      /* 21rem is width of the nav bar in full-screen mode. */
-      max-width: calc(90vw - 21rem);
-    }
-  }
-  .message-body:empty:after {
-    content: '.';
-    visibility: hidden;
-  }
-  /* Without the global selector, the Svelte CSS compiler will see this as
-   * unused, and purge it from the output. However, this is "plausibly used"
-   * because it may occur in renderedBody.
-   */
-  :global(.message-body blockquote) {
-    border-left: 0.25rem solid lightgrey;
-    margin-left: 0.5rem;
-    padding-left: 0.5rem;
-  }
-  :global(.message-body pre) {
-    border: 1px solid #312e81;
-    border-radius: 0.25rem;
-    background-color: #282555;;
-    padding: 0.25rem;
-  }
-</style>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index 6cad381..09388ac 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -9,6 +9,7 @@
 </script>
 
 <div
+  class="message-run"
   class:own-message={ownMessage}
   class:other-message={!ownMessage}
 >
@@ -19,17 +20,3 @@
     <Message {...message} editable={ownMessage} />
   {/each}
 </div>
-
-<style>
-  .own-message {
-    background-color: rgb(32, 42, 74);
-  }
-  /* Honestly, I don't love scoping styles per component, and this is a great
-   * example of why. MessageRuns know if they're own-message, but Messages in
-   * them need to get a style based on that fact. I don't wanna bucket-brigade
-   * that fact into the Message, when it's a pure CSS concern.
-   */
-  .own-message :global(*) {
-    color: rgb(198, 198, 198);
-  }
-</style>
diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte
index 8a70c4b..cacfc2d 100644
--- a/ui/routes/(app)/+layout.svelte
+++ b/ui/routes/(app)/+layout.svelte
@@ -126,63 +126,19 @@
 {#if loading}
   <h2>Loading&hellip;</h2>
 {:else}
-  <div id="interface" class="p-2">
+  <div id="interface">
     <nav id="sidebar" data-expanded={pageContext.showMenu}>
-      <div class="channel-list">
         <ChannelList active={channel} channels={enrichedChannels} />
+        <!--
+      <div class="channel-list">
       </div>
+        -->
       <div class="create-channel">
         <CreateChannelForm />
       </div>
     </nav>
-    <main class="pl-4">
+    <main>
       {@render children?.()}
     </main>
   </div>
 {/if}
-
-<style>
-  #interface {
-    margin: unset;
-    display: grid;
-    grid-template:
-      'side main' 1fr
-      / auto 1fr;
-    height: calc(100vh - var(--app-bar-height));
-
-    @media (width > 640px) {
-      --overlay: static;
-      --translate: 0;
-    }
-  }
-  nav {
-    grid-area: side;
-    background-color: rgb(var(--color-surface-800));
-    inset: auto auto 0 0;
-    padding: 0.25rem;
-    position: var(--overlay, absolute);
-    transition: translate 300ms ease-out;
-    width: var(--nav-width);
-    height: 100vh;
-    @media (width > 640px) {
-      height: calc(100vh - var(--app-bar-height) - var(--interface-padding));
-    }
-    z-index: 10;
-    border-top-right-radius: 1.4rem;
-    border-bottom-right-radius: 1.4rem;
-  }
-  main {
-    grid-area: main;
-    height: calc(100vh - var(--app-bar-height) - var(--interface-padding));
-  }
-  .channel-list {
-    height: calc(100vh - var(--input-row-height));
-    @media (width > 640px) {
-      height: calc(100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding));
-    }
-    overflow: auto;
-  }
-  nav[data-expanded='false'] {
-    translate: var(--translate, -100% 0);
-  }
-</style>
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index d4e04fe..8eba709 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -67,24 +67,6 @@
 <div class="active-channel" on:scroll={handleScroll} bind:this={activeChannel}>
   <ActiveChannel {messageRuns} />
 </div>
-<div class="create-message max-h-full">
+<div class="create-message">
   <MessageInput {channel} />
 </div>
-
-<style>
-  .active-channel {
-    height: calc(
-      100vh - var(--app-bar-height) - var(--interface-padding) - var(--input-row-height)
-    );
-    overflow: auto;
-  }
-  .create-message {
-    position: fixed;
-    bottom: 0.5rem;
-    width: calc(100% - var(--nav-width) - 2rem);
-    @media (width <= 640px) {
-      width: 100%;
-      left: 0;
-    }
-  }
-</style>
diff --git a/ui/styles/active-channel.css b/ui/styles/active-channel.css
new file mode 100644
index 0000000..6efc3e3
--- /dev/null
+++ b/ui/styles/active-channel.css
@@ -0,0 +1,3 @@
+.active-channel {
+  padding: 1rem;
+}
diff --git a/ui/styles/app-bar.css b/ui/styles/app-bar.css
index 401a278..caa50ed 100644
--- a/ui/styles/app-bar.css
+++ b/ui/styles/app-bar.css
@@ -5,6 +5,7 @@
   flex-direction: row;
   justify-content: space-between;
   align-items: stretch;
+  background-color: var(--colour-background);
 }
 
 .app-bar > * {
diff --git a/ui/styles/app-layout.css b/ui/styles/app-layout.css
new file mode 100644
index 0000000..ef1eb10
--- /dev/null
+++ b/ui/styles/app-layout.css
@@ -0,0 +1,56 @@
+/* TODO: generally remove literals from this file. */
+
+#interface {
+  margin: unset;
+  display: grid;
+  grid-template:
+    'side main' 1fr
+    / auto 1fr;
+  height: calc(100vh - var(--app-bar-height));
+
+  @media (width > 640px) {
+    --overlay: static;
+    --translate: 0;
+  }
+}
+
+nav#sidebar {
+  grid-area: side;
+  inset: auto auto 0 0;
+  padding-right: 0.5rem;
+  position: var(--overlay, absolute);
+  transition: translate 300ms ease-out;
+  width: var(--nav-width);
+  height: 100vh;
+  z-index: 10;
+
+  border-radius: 0 1.4rem 1.4rem 0;
+
+  background-color: var(--colour-background-alt);
+
+  @media (width > 640px) {
+    height: calc(100vh - var(--app-bar-height));
+  }
+}
+
+nav.list-nav {
+  height: calc(100vh - var(--input-row-height) - var(--interface-padding));
+  overflow: auto;
+
+  @media (width > 640px) {
+    height: calc(100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding));
+  }
+}
+
+main {
+  grid-area: main;
+  height: calc(100vh - var(--app-bar-height));
+}
+
+main textarea {
+  resize: none;
+}
+
+nav[data-expanded='false'] {
+  translate: var(--translate, -100% 0);
+}
diff --git a/ui/styles/messages.css b/ui/styles/messages.css
new file mode 100644
index 0000000..bd46baf
--- /dev/null
+++ b/ui/styles/messages.css
@@ -0,0 +1,83 @@
+.message-run {
+  position: relative;
+  border-radius: 0.25rem;
+  border: 1px solid var(--colour-border);
+  padding: 0 0 0.5rem 0;
+  margin-bottom: 1rem;
+  box-shadow: 0 0.25rem 0.25rem rgba(0, 0, 0, 0.5);
+}
+
+/* TODO: replace these with colour variables. */
+.own-message {
+  background-color: rgb(32, 42, 74);
+}
+
+.own-message * {
+  color: rgb(198, 198, 198);
+}
+
+.message-run > span {
+  /* Username */
+  color: var(--colour-text);
+  background-color: rgb(67, 88, 156);
+}
+
+.message {
+  padding: 0.5rem 0 0 0.5rem;
+}
+
+.message:hover {
+  background-color: rgb(21, 28, 49);
+}
+
+.message .handle {
+  --text-size: 0.5rem;
+  float: right;
+  line-height: var(--text-size);
+  font-size: var(--text-size);
+  top: -0.5rem;
+  position: relative;
+  padding: 0.25rem;
+  border-radius: 0.25rem;
+  display: none;
+  background-color: rgb(67, 88, 156);
+}
+
+.message:hover .handle {
+  display: flex;
+}
+
+.message .handle button {
+  line-height: 0.35rem;
+  background: none;
+  border: none;
+  cursor: pointer;
+}
+
+.message-body {
+  overflow: auto;
+  max-width: 80vw;
+
+  @media (width > 640px) {
+    /* 21rem is width of the nav bar in full-screen mode. */
+    max-width: calc(90vw - 21rem);
+  }
+}
+
+.message-body:empty:after {
+  content: '.';
+  visibility: hidden;
+}
+
+/* For rendered message bodies: */
+.message-body blockquote {
+  border-left: 0.25rem solid lightgrey;
+  margin-left: 0.5rem;
+  padding-left: 0.5rem;
+}
+.message-body pre {
+  border: 1px solid #312e81;
+  border-radius: 0.25rem;
+  background-color: #282555;;
+  padding: 0.25rem;
+}
diff --git a/ui/styles/sidebar.css b/ui/styles/sidebar.css
index e512847..e9098f2 100644
--- a/ui/styles/sidebar.css
+++ b/ui/styles/sidebar.css
@@ -3,6 +3,10 @@
   background-color: var(--colour-background-alt);
 }
 
+.list-nav ul {
+  padding: 0.5rem;
+}
+
 .list-nav li {
   padding: 0.5rem;
   border-radius: 0.5rem;
@@ -32,8 +36,15 @@
   border: 1px solid var(--colour-border);
   z-index: 1;  /* Just to make the focus-active border go over the following button. */
   flex-grow: 1;
+  background-color: var(--colour-text);
+  color: var(--colour-background);
 }
 
 .create-channel button {
   border-radius: 0 0.5rem 0.5rem 0;
+  border: 1px solid var(--colour-border);
+  background-color: var(--colour-text);
+  color: var(--colour-background);
 }
+
+/* TODO: media-query stuff. Margin-left at a constant zero? */
diff --git a/ui/styles/textarea.css b/ui/styles/textarea.css
new file mode 100644
index 0000000..72d727f
--- /dev/null
+++ b/ui/styles/textarea.css
@@ -0,0 +1,38 @@
+/* Message input */
+.create-message form {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  align-items: stretch;
+}
+
+.create-message textarea {
+  padding: 0.5rem;
+  border-radius: 0.5rem 0 0 0.5rem;
+  border: 1px solid var(--colour-border);
+  z-index: 1;  /* Just to make the focus-active border go over the following button. */
+  flex-grow: 1;
+  background-color: var(--colour-text);
+  color: var(--colour-background);
+}
+
+.create-message button {
+  border-radius: 0 0.5rem 0.5rem 0;
+  border: 1px solid var(--colour-border);
+  background-color: var(--colour-text);
+  color: var(--colour-background);
+}
+
+.active-channel {
+  overflow: auto;
+  flex-grow: 1;
+  /* TODO: make this all-app background */
+  background-color: var(--colour-background);
+}
+
+main {
+  display: flex;
+  flex-direction: column;
+  justify-content: flex-start;
+  align-items: stretch;
+}
diff --git a/ui/styles/variables.css b/ui/styles/variables.css
index e948c71..5ea4d74 100644
--- a/ui/styles/variables.css
+++ b/ui/styles/variables.css
@@ -8,11 +8,25 @@
   --nav-width: 21rem;
 
   /* coloUrs */
-  --colour-background: rgba(0, 0, 0, 0.25);
-  --colour-background-alt: rgba(0, 0, 0, 0.35);
-  --colour-border: rgba(0, 0, 0, 0.45);
-  --colour-text: rgb(240, 240, 240);
-  --colour-okay: #2a9d8f;
-  --colour-warn: #e9c46a;
-  --colour-error: #e76f51;
+  /* Really, we need:
+   * - Dark header background
+   * - Medium sidebar background
+   * - Light channel background
+   * - okay/warn/error
+   * - Border colours?
+   * - Text colour
+   * - Hover colour
+   * - Active colour
+   */
+  --colour-background: #253031;
+  --colour-border: #192122;
+
+  --colour-background-alt: #426A5A;
+  --colour-border-alt: #2E4A3E;
+
+  --colour-text: #FFFFEA;
+
+  --colour-okay: #6A994E;
+  --colour-warn: #EBC3BE;
+  --colour-error: #DE5F55;
 }
-- 
cgit v1.2.3


From 6d51f8568e337e768505ccfdef916b84dd6eb1b3 Mon Sep 17 00:00:00 2001
From: Owen Jacobson <owen@grimoire.ca>
Date: Sat, 11 Jan 2025 13:34:13 -0500
Subject: npm run format

---
 ui/app.css                                 |  22 ++---
 ui/lib/components/ChangePassword.svelte    |   7 +-
 ui/lib/components/Channel.svelte           |   2 +-
 ui/lib/components/CreateChannelForm.svelte |   7 +-
 ui/lib/components/LogIn.svelte             |   8 +-
 ui/lib/components/Message.svelte           |   8 +-
 ui/lib/components/MessageInput.svelte      |  11 +--
 ui/lib/components/MessageRun.svelte        |   6 +-
 ui/lib/store/channels.svelte.js            |   9 +-
 ui/lib/store/messages.svelte.js            |   2 +-
 ui/routes/(app)/+layout.svelte             |   6 +-
 ui/routes/(app)/+page.svelte               |   4 +-
 ui/routes/(app)/ch/[channel]/+page.svelte  |  14 +--
 ui/styles/app-layout.css                   |   4 +-
 ui/styles/reset.css                        | 147 ++++++++++++++++++++++-------
 ui/styles/sidebar.css                      |   2 +-
 ui/styles/textarea.css                     |   2 +-
 ui/styles/variables.css                    |  18 +++-
 18 files changed, 167 insertions(+), 112 deletions(-)

(limited to 'ui/routes/(app)/ch/[channel]/+page.svelte')

diff --git a/ui/app.css b/ui/app.css
index 2df588e..a02106d 100644
--- a/ui/app.css
+++ b/ui/app.css
@@ -1,14 +1,14 @@
-@import url("styles/reset.css");
-@import url("styles/variables.css");
-@import url("styles/overscroll.css");
-@import url("styles/app-bar.css");
-@import url("styles/app-layout.css");
-@import url("styles/sidebar.css");
-@import url("styles/active-channel.css");
-@import url("styles/messages.css");
-@import url("styles/textarea.css");
-@import url("styles/forms.css");
-@import url("styles/invites.css");
+@import url('styles/reset.css');
+@import url('styles/variables.css');
+@import url('styles/overscroll.css');
+@import url('styles/app-bar.css');
+@import url('styles/app-layout.css');
+@import url('styles/sidebar.css');
+@import url('styles/active-channel.css');
+@import url('styles/messages.css');
+@import url('styles/textarea.css');
+@import url('styles/forms.css');
+@import url('styles/invites.css');
 
 body {
   background-color: var(--colour-active-channel-bg);
diff --git a/ui/lib/components/ChangePassword.svelte b/ui/lib/components/ChangePassword.svelte
index 51ebccd..bf94ea7 100644
--- a/ui/lib/components/ChangePassword.svelte
+++ b/ui/lib/components/ChangePassword.svelte
@@ -35,12 +35,7 @@
 
   <label
     >new password
-    <input
-      name="newPassword"
-      type="password"
-      placeholder="password"
-      bind:value={newPassword}
-    />
+    <input name="newPassword" type="password" placeholder="password" bind:value={newPassword} />
   </label>
 
   <label
diff --git a/ui/lib/components/Channel.svelte b/ui/lib/components/Channel.svelte
index 2fc3249..c73340f 100644
--- a/ui/lib/components/Channel.svelte
+++ b/ui/lib/components/Channel.svelte
@@ -3,7 +3,7 @@
 </script>
 
 <a href="/ch/{id}">
-  <li class:active={active}>
+  <li class:active>
     {#if hasUnreads}
       <span class="badge has-unreads">❦</span>
     {:else}
diff --git a/ui/lib/components/CreateChannelForm.svelte b/ui/lib/components/CreateChannelForm.svelte
index 8fab4c4..85c85bb 100644
--- a/ui/lib/components/CreateChannelForm.svelte
+++ b/ui/lib/components/CreateChannelForm.svelte
@@ -16,11 +16,6 @@
 </script>
 
 <form onsubmit={handleSubmit}>
-  <input
-    type="text"
-    placeholder="create channel"
-    bind:value={name}
-    {disabled}
-  />
+  <input type="text" placeholder="create channel" bind:value={name} {disabled} />
   <button type="submit">&#x2795;</button>
 </form>
diff --git a/ui/lib/components/LogIn.svelte b/ui/lib/components/LogIn.svelte
index 44aab44..5bfdae2 100644
--- a/ui/lib/components/LogIn.svelte
+++ b/ui/lib/components/LogIn.svelte
@@ -12,13 +12,7 @@
   <form class="form" {onsubmit}>
     <label for="username">
       username
-      <input
-        name="username"
-        type="text"
-        placeholder="username"
-        bind:value={username}
-        {disabled}
-      />
+      <input name="username" type="text" placeholder="username" bind:value={username} {disabled} />
     </label>
     <label for="password">
       password
diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte
index 6918b5d..1b1598b 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -25,13 +25,7 @@
   }
 </script>
 
-<div
-    class="message"
-    class:delete-armed={deleteArmed}
-    role="article"
-    data-at={at}
-    {onmouseleave}
-    >
+<div class="message" class:delete-armed={deleteArmed} role="article" data-at={at} {onmouseleave}>
   <div class="handle">
     {atFormatted}
     {#if editable}
diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte
index 25a0352..162db1b 100644
--- a/ui/lib/components/MessageInput.svelte
+++ b/ui/lib/components/MessageInput.svelte
@@ -24,13 +24,6 @@
 </script>
 
 <form bind:this={form} onsubmit={onSubmit}>
-  <textarea
-    onkeydown={onKeyDown}
-    bind:value
-    {disabled}
-    type="search"
-  ></textarea>
-  <button
-    type="submit"
-  >&raquo;</button>
+  <textarea onkeydown={onKeyDown} bind:value {disabled} type="search"></textarea>
+  <button type="submit">&raquo;</button>
 </form>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index dec5f4f..bee64e8 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -8,11 +8,7 @@
   let ownMessage = $derived($currentUser !== null && $currentUser.id == sender);
 </script>
 
-<div
-  class="message-run"
-  class:own-message={ownMessage}
-  class:other-message={!ownMessage}
->
+<div class="message-run" class:own-message={ownMessage} class:other-message={!ownMessage}>
   <span class="username">
     @{name}:
   </span>
diff --git a/ui/lib/store/channels.svelte.js b/ui/lib/store/channels.svelte.js
index 8919be0..c82f9aa 100644
--- a/ui/lib/store/channels.svelte.js
+++ b/ui/lib/store/channels.svelte.js
@@ -1,5 +1,5 @@
 import { DateTime } from 'luxon';
-const EPOCH_STRING = "1970-01-01T00:00:00Z";
+const EPOCH_STRING = '1970-01-01T00:00:00Z';
 
 // For reasons unclear to me, a straight up class definition with a constructor
 // doesn't seem to work, reactively. So we resort to this.
@@ -15,7 +15,7 @@ function makeChannelObject({ id, name, draft = '', lastReadAt = null, scrollPosi
     name,
     lastReadAt: lastReadAt || DateTime.fromISO(EPOCH_STRING),
     draft,
-    scrollPosition,
+    scrollPosition
   };
 }
 
@@ -33,10 +33,7 @@ export class Channels {
   }
 
   addChannel(id, name) {
-    this.channels = [
-      ...this.channels,
-      makeChannelObject({ id, name }),
-    ];
+    this.channels = [...this.channels, makeChannelObject({ id, name })];
     this.sort();
     return this;
   }
diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js
index ba4c895..dadade6 100644
--- a/ui/lib/store/messages.svelte.js
+++ b/ui/lib/store/messages.svelte.js
@@ -5,7 +5,7 @@ import DOMPurify from 'dompurify';
 const RUN_COALESCE_MAX_INTERVAL = 10 /* min */ * 60 /* sec */ * 1000; /* ms */
 
 export class Messages {
-  channels = $state({});  // Mapping<ChannelId, Message>
+  channels = $state({}); // Mapping<ChannelId, Message>
 
   inChannel(channel) {
     return this.channels[channel] || [];
diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte
index 08444bd..cbfef54 100644
--- a/ui/routes/(app)/+layout.svelte
+++ b/ui/routes/(app)/+layout.svelte
@@ -41,7 +41,7 @@
         let hasUnreads = lastMessageAt > ch.lastReadAt;
         enrichedChannels.push({
           ...ch,
-          hasUnreads,
+          hasUnreads
         });
       }
     }
@@ -116,7 +116,7 @@
   }
 </script>
 
-<svelte:window on:beforeunload={beforeUnload}/>
+<svelte:window on:beforeunload={beforeUnload} />
 
 <svelte:head>
   <!-- TODO: unread count? -->
@@ -128,7 +128,7 @@
 {:else}
   <div id="interface">
     <nav id="sidebar" data-expanded={pageContext.showMenu}>
-        <ChannelList active={channel} channels={enrichedChannels} />
+      <ChannelList active={channel} channels={enrichedChannels} />
       <div class="create-channel">
         <CreateChannelForm />
       </div>
diff --git a/ui/routes/(app)/+page.svelte b/ui/routes/(app)/+page.svelte
index e15bca8..007c5c6 100644
--- a/ui/routes/(app)/+page.svelte
+++ b/ui/routes/(app)/+page.svelte
@@ -1,5 +1,3 @@
 <div class="no-active-channel">
-  <span class="vertical-aligner">
-    Please select or create a channel.
-  </span>
+  <span class="vertical-aligner"> Please select or create a channel. </span>
 </div>
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index 8eba709..dbdb507 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -18,15 +18,17 @@
     const elementTop = elRect.top;
     const elementBottom = elRect.bottom;
 
-    return ((parentTop < elementTop) && (parentBottom > elementBottom));
+    return parentTop < elementTop && parentBottom > elementBottom;
   }
 
   function getLastVisibleMessage() {
     const parentElement = activeChannel;
     const childElements = parentElement.getElementsByClassName('message');
-    const lastInView = Array.from(childElements).reverse().find((el) => {
-      return inView(parentElement, el);
-    });
+    const lastInView = Array.from(childElements)
+      .reverse()
+      .find((el) => {
+        return inView(parentElement, el);
+      });
     return lastInView;
   }
 
@@ -50,14 +52,14 @@
   });
 
   function handleKeydown(event) {
-		if (event.key === 'Escape') {
+    if (event.key === 'Escape') {
       setLastRead(); // TODO: pass in "last message DT"?
     }
   }
 
   let lastReadCallback = null;
   function handleScroll() {
-    clearTimeout(lastReadCallback);  // Fine if lastReadCallback is null still.
+    clearTimeout(lastReadCallback); // Fine if lastReadCallback is null still.
     lastReadCallback = setTimeout(setLastRead, 2 * 1000);
   }
 </script>
diff --git a/ui/styles/app-layout.css b/ui/styles/app-layout.css
index 50fa704..82d9914 100644
--- a/ui/styles/app-layout.css
+++ b/ui/styles/app-layout.css
@@ -36,7 +36,9 @@ nav.list-nav {
   overflow: auto;
 
   @media (width > 640px) {
-    height: calc(100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding));
+    height: calc(
+      100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding)
+    );
   }
 }
 
diff --git a/ui/styles/reset.css b/ui/styles/reset.css
index e29c0f5..a3f7681 100644
--- a/ui/styles/reset.css
+++ b/ui/styles/reset.css
@@ -3,46 +3,127 @@
    License: none (public domain)
 */
 
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed, 
-figure, figcaption, footer, header, hgroup, 
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
-	margin: 0;
-	padding: 0;
-	border: 0;
-	font-size: 100%;
-	font: inherit;
-	vertical-align: baseline;
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+  margin: 0;
+  padding: 0;
+  border: 0;
+  font-size: 100%;
+  font: inherit;
+  vertical-align: baseline;
 }
 /* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure, 
-footer, header, hgroup, menu, nav, section {
-	display: block;
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+  display: block;
 }
 body {
-	line-height: 1;
+  line-height: 1;
 }
-ol, ul {
-	list-style: none;
+ol,
+ul {
+  list-style: none;
 }
-blockquote, q {
-	quotes: none;
+blockquote,
+q {
+  quotes: none;
 }
-blockquote:before, blockquote:after,
-q:before, q:after {
-	content: '';
-	content: none;
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+  content: '';
+  content: none;
 }
 table {
-	border-collapse: collapse;
-	border-spacing: 0;
+  border-collapse: collapse;
+  border-spacing: 0;
 }
diff --git a/ui/styles/sidebar.css b/ui/styles/sidebar.css
index b31c4fd..5e5e16a 100644
--- a/ui/styles/sidebar.css
+++ b/ui/styles/sidebar.css
@@ -44,7 +44,7 @@
   padding: 0.5rem;
   border-radius: 0.5rem 0 0 0.5rem;
   border: 1px solid var(--colour-input-border);
-  z-index: 1;  /* Just to make the focus-active border go over the following button. */
+  z-index: 1; /* Just to make the focus-active border go over the following button. */
   flex-grow: 1;
   background-color: var(--colour-input-bg);
   color: var(--colour-input-text);
diff --git a/ui/styles/textarea.css b/ui/styles/textarea.css
index b45a66d..c38de46 100644
--- a/ui/styles/textarea.css
+++ b/ui/styles/textarea.css
@@ -10,7 +10,7 @@
   padding: 0.5rem;
   border-radius: 0.5rem 0 0 0.5rem;
   border: 1px solid var(--colour-input-border);
-  z-index: 1;  /* Just to make the focus-active border go over the following button. */
+  z-index: 1; /* Just to make the focus-active border go over the following button. */
   flex-grow: 1;
   background-color: var(--colour-input-bg);
   color: var(--colour-input-text);
diff --git a/ui/styles/variables.css b/ui/styles/variables.css
index fa51506..80817f3 100644
--- a/ui/styles/variables.css
+++ b/ui/styles/variables.css
@@ -8,9 +8,9 @@
   --nav-width: 21rem;
 
   /* coloUrs */
-  --colour-okay: #6A994E;
-  --colour-warn: #EBC3BE;
-  --colour-error: #DE5F55;
+  --colour-okay: #6a994e;
+  --colour-warn: #ebc3be;
+  --colour-error: #de5f55;
 
   /* I dunno, I liked this colour: */
   --colour-base: rgb(121, 96, 159);
@@ -43,9 +43,17 @@
 
   /* MessageRun */
   --colour-message-run-self-bg: color-mix(in srgb, var(--colour-base) 30%, white);
-  --colour-message-run-self-border: color-mix(in srgb, var(--colour-message-run-self-bg) 50%, black);
+  --colour-message-run-self-border: color-mix(
+    in srgb,
+    var(--colour-message-run-self-bg) 50%,
+    black
+  );
   --colour-message-run-other-bg: color-mix(in srgb, var(--colour-base) 50%, white);
-  --colour-message-run-other-border: color-mix(in srgb, var(--colour-message-run-other-bg) 50%, black);
+  --colour-message-run-other-border: color-mix(
+    in srgb,
+    var(--colour-message-run-other-bg) 50%,
+    black
+  );
   --colour-message-run-self-text: var(--dark-text);
   --colour-message-run-other-text: var(--dark-text);
 
-- 
cgit v1.2.3

